/**     
* @Title: AbstractThread.java   
* @Package me.crawler.crawl   
* @Description: TODO   
* @author xaoyaoyao
* @date 2019年1月19日 上午11:24:24
*/
package me.crawler.crawl;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;
import me.crawler.downloader.HttpDownloader;
import me.crawler.entity.SpiderSeed;
import me.crawler.entity.SpiderTask;
import me.crawler.enumerate.ResultEnum;
import me.crawler.init.ReptileData;
import me.crawler.parser.XmlParser;
import me.crawler.processor.AbstractProcessor;
import me.crawler.util.StopSignalReceiver;

/**
 * @ClassName: AbstractThread
 * @Description: TODO
 * @author xaoyaoyao
 * @date 2019年1月19日 上午11:24:24
 * 
 */
@Slf4j
public abstract class AbstractThread<T> implements Runnable {

	private AbstractProcessor<T> processor;

	private boolean async;

	private Class<T> clazz;

	public AbstractThread(AbstractProcessor<T> processor, boolean async, Class<T> clazz) {
		super();
		this.processor = processor;
		this.async = async;
		this.clazz = clazz;
	}

	@Override
	public void run() {
		log.error(">>>>>>>> 开始执行任务...");
		while (!isExit()) {
			try {
				SpiderTask task = getGrabTask();
				if (null == task) {
					Thread.sleep(15000);// 15s
					continue;
				}
				String htmlTxt = HttpDownloader.builder().task(task).build().download();
				log.debug(">>>>>>>> htmlTxt >> {}", htmlTxt);
				List<SpiderSeed> seeds = getSpiderSeeds().get(task.getDomain());
				ResultEnum resultEnum = ResultEnum.ERROR;
				// 默认失败
				if (StringUtils.isNoneBlank(htmlTxt)) {
					// 处理结果
					T result = XmlParser.builder().htmlTxt(htmlTxt).seeds(seeds).build().parse(clazz);
					resultEnum = handle(result);
				}
				// 提交任务
				submitResult(task, resultEnum);
			} catch (Exception e) {
				log.error(">>>>>>>> Check Thread Exception!", e);
			}
		}
		if (isExit()) {
			log.error(">>>>>>>> 关闭任务！！！");
		}
	}

	private SpiderTask getGrabTask() {
		return ReptileData.getGrabTask();
	}

	private Map<String, List<SpiderSeed>> getSpiderSeeds() {
		return ReptileData.getSpiderSeeds();
	}

	public abstract void submitResult(SpiderTask task, ResultEnum resultEnum);

	private ResultEnum handle(T result) {
		if (async) { // 异步
			Future<ResultEnum> future = processor.asyncProcess(result);
			log.info(">>>>>>>> 执行结果 >> {}", future);
			try {
				return future.get();
			} catch (InterruptedException e) {
				log.error(e.getMessage(), e);
			} catch (ExecutionException e) {
				log.error(e.getMessage(), e);
			}
			return ResultEnum.ERROR;
		}
		ResultEnum resultEnum = processor.process(result);
		log.info(">>>>>>>> 执行结果 >> {}", resultEnum);
		return resultEnum;
	}

	private boolean isExit() {
		return StopSignalReceiver.isReceived();
	}
}
